﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Moq;
using Moq.Protected;

namespace MoqContrib.AutoMock.Tests.AutoMockingContainers
{
    [TestFixture]
    public class WhenDoingAUnion
    {
        Mock<AutoMockHelper> _helper;
        Func<Type, bool, Mock> MockThatWasRemoved { get; set; }

        #region Types used for testing
        public interface IParentService { }
        public interface IService1 : IParentService { }
        public interface IService2 : IParentService { }
        public class Service1 : IService1 { }
        public class Service2 : IService2 { }
        #endregion

        [SetUp]
        public void Given()
        {
            // Mock protected abstract members
            _helper = new Mock<AutoMockHelper>();
            _helper.CallBase = true;
            MockThatWasRemoved = (t,f) => null;
        }

        [Test]
        public void parent_and_child_interfaces_can_be_unioned()
        {
            var mock = _helper.Object.Union<IService1, IParentService>();

            Assert.That(mock.Object, Is.InstanceOf<IParentService>());
            Assert.That(mock.Object, Is.InstanceOf<IService1>());
            _helper.Protected().Verify("RegisterInstance", Times.Once(),
                ItExpr.IsAny<Type[]>(), ItExpr.IsAny<object>());
        }

        [Test]
        public void parent_interface_and_child_class_can_be_unioned()
        {
            var mock = _helper.Object.Union<Service1, IService1>();

            Assert.That(mock.Object, Is.InstanceOf<Service1>());
            Assert.That(mock.Object, Is.InstanceOf<IService1>());
            _helper.Protected().Verify("RegisterInstance", Times.Once(),
                ItExpr.IsAny<Type[]>(), ItExpr.IsAny<object>());
        }

        [Test]
        public void sibling_interfaces_can_be_unioned()
        {
            var mock = _helper.Object.Union<IService1, IService2>();

            Assert.That(mock.Object, Is.InstanceOf<IService2>());
            Assert.That(mock.Object, Is.InstanceOf<IService1>());
            _helper.Protected().Verify("RegisterInstance", Times.Once(),
                ItExpr.IsAny<Type[]>(), ItExpr.IsAny<object>());
        }

        [Test]
        public void sibling_classes_cannot_be_unioned()
        {
            Assert.Throws<ArgumentException>(() => _helper.Object.Union<Service1, Service2>());
        }

    }
}
